package com.core.snowflake.config;


import com.core.snowflake.core.SnowFlakeUtil;
import com.core.snowflake.service.SnowFlakeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import java.io.*;
import java.net.InetAddress;
import java.util.UUID;

@Order(2000)
@Configuration
@ComponentScan("com.core.snowflake")//重要：此语句左右，告诉应用宿主程序，扫描com.core.snowflake下所有注入
@EnableConfigurationProperties(SnowFlakeProperties.class)
public class SnowFlakeConfiguration {

    Logger log  = LoggerFactory.getLogger("snowFlakeUnit");

    @Value("${snowflake.salt:}")
    private  String _secret;

    /**
     * 初始化程序
     */
    @PostConstruct
    public void init() {
        if (_secret != null && !_secret.equals(""))
            SnowConst.secret = _secret;
        log.info("WellCome to 雪花ID中心(支持模式:auto、manual、datacenter、redis)");
    }

    /**
     * 数据中心模式
     * @return
     */
    @Bean
    @ConditionalOnProperty("snowflake.type")
    @ConditionalOnMissingBean(SnowFlakeUtil.class)
    public SnowFlakeUtil snowFlakeUtil(SnowFlakeProperties snowFlakeProperties) throws Exception {
        SnowFlakeUtil sf = null;
        if (snowFlakeProperties.getType().equals("auto")) {
            //自动默认模式 （1，1）
             sf = new SnowFlakeUtil(false);
        }
        if (snowFlakeProperties.getType().equals("manual"))
        {
            //手动设置 workerId  datacenterId
            Assert.notNull(snowFlakeProperties.getWorkerId(), "workerId 不能为 null!");
            Assert.notNull(snowFlakeProperties.getDatacenterId(), "datacenterId 不能为 null!");
            sf = new SnowFlakeUtil(snowFlakeProperties.getWorkerId(),snowFlakeProperties.getDatacenterId());
        }
        else if (snowFlakeProperties.getType().equals("datacenter") || snowFlakeProperties.getType().equals("redis"))
        {
            //从数据中心自动获取（延迟X秒后，自动从数据中心拉取）
            sf = new SnowFlakeUtil(true);
            //从配置文件获取唯一key,只在第一次启动时候生成
            //修改策略，每次启动都生成唯一UUID，不和本地文件绑定---》为了 分布式--》docker -->同步映射到同一个文件
            //sf.setSyncTag(UUID.randomUUID().toString());
            //采用本机IP作为SyncTag
            String localIp = "127.0.0.1";
            try {
                InetAddress.getLocalHost().getHostAddress();
            }
            catch (Exception ex)
            {

            }
            sf.setSyncTag(localIp);
        }
        else
            throw new Exception("配置文件不正确");
        return sf;
    }


    /**
     * 雪花专用rest
     * @return
     */
    @Bean(name = "sn_restTemplate")
    @ConditionalOnProperty(value = "snowflake.type",havingValue="datacenter")
    public RestTemplate RestTemplate() {
        /*
        // 添加代理
        //todo 暂时不考虑，等有业务了，再进行
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
        simpleClientHttpRequestFactory.setProxy(new Proxy(Proxy.Type.HTTP,new InetSocketAddress("XXX",8080))); // 添加代理 ip 和 port 即可
        restTemplate.setRequestFactory(simpleClientHttpRequestFactory);
        return restTemplate;
    }

        HttpComponentsClientHttpRequestFactory httpsFactory = new HttpComponentsClientHttpRequestFactory();
        //配置HTTP超时时间 单位是毫秒
        httpsFactory.setConnectTimeout(300000);
        httpsFactory.setReadTimeout(300000);
        httpsFactory.setConnectionRequestTimeout(300000);
        RestTemplate restTemplate = new RestTemplate(httpsFactory);

         */
        return new RestTemplate();
    }



    /**
     * 数据中心同步守护进程-心跳
     * (datacenter模式)
     *
     * @return
     */
    @Order(2001)
    @Bean
    @ConditionalOnProperty(value = "snowflake.type",havingValue="datacenter")
    @ConditionalOnBean(SnowFlakeUtil.class)
    public SnowFlakeService snowFlakeService_dataCenter(SnowFlakeUtil snowFlakeUtil, SnowFlakeProperties snowFlakeProperties) {
      return   intSnowFlakeService(snowFlakeUtil,snowFlakeProperties);
    }

    /**
     * 数据中心同步守护进程-心跳
     * (直读redis模式)
     *
     * @return
     */
    @Order(2002)
    @Bean
    @ConditionalOnProperty(value = "snowflake.type",havingValue="redis")
    @ConditionalOnBean(SnowFlakeUtil.class)
    public SnowFlakeService snowFlakeService_redis(SnowFlakeUtil snowFlakeUtil, SnowFlakeProperties snowFlakeProperties) {
      return   intSnowFlakeService(snowFlakeUtil,snowFlakeProperties);
    }

    private SnowFlakeService intSnowFlakeService(SnowFlakeUtil snowFlakeUtil, SnowFlakeProperties snowFlakeProperties)
    {
        //Assert.notNull(okHttpUtil,"雪花算法：OkHttpUtill包未注册,数据中心自动配置需要此包");
        Assert.notNull(snowFlakeUtil,"snowFlakeUtil 未初始化");
        Assert.notNull(snowFlakeProperties,"snowFlake配置 未初始化");


        return new SnowFlakeService(snowFlakeUtil,snowFlakeProperties);
    }


    private String getKeyFile() {
        String filename = "./SnowFlake.key"; // 绝对路径或相对路径都可以
        // String pathname = "//SnowFlake.key"; // 绝对路径或相对路径都可以
        File targetFile = new File(filename); // 要读取以上路径的input。txt文件
        String line = "";
        BufferedReader br = null;
        InputStreamReader reader = null;
        BufferedWriter out = null;
        try {
            if (!targetFile.exists()) {
                targetFile.createNewFile();
                //---------------写入---------------------------
                out = new BufferedWriter(new FileWriter(targetFile));
                out.write(UUID.randomUUID().toString()); // \r\n即为换行
                out.flush(); // 把缓存区内容压入文件
                out.close(); // 最后记得关闭文件
                //---------------------------------------------------
            }
            //---------------------读取-------------------------
            reader = new InputStreamReader(
                    new FileInputStream(targetFile)); // 建立一个输入流对象reader
            br = new BufferedReader(reader); // 建立一个对象，它把文件内容转成计算机能读懂的语言
            StringBuffer sbf = new StringBuffer();
            String tmp = null;//br.readLine();
            while ((tmp = br.readLine()) != null) {
                // line = br.readLine(); // 一次读入一行数据
                // line+=tmp;
                sbf.append(tmp);
            }
            line = sbf.toString();
            //---------------------------------------------------------
        } catch (Exception ex) {
            log.error("创建雪花ID出错" + ex.toString());
            line = "";
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return line;

    }
}
